package cc.wfu.trigger.http;

import cc.common.types.entity.ShopCartEntity;
import cc.common.types.entity.UserEntity;
import cc.wfu.domain.order.event.OrderMessageEvent;
import cc.wfu.domain.order.model.entity.SkuRechargeOrderEntity;
import cc.wfu.domain.order.service.IProductOrder;
import cc.wfu.domain.order.service.rule.armory.IProductActivityArmory;
import cc.wfu.infrastructure.event.EventPublisher;
import cc.wfu.trigger.api.SaleApi;
import cc.wfu.type.service.JwtAuthService;
import cc.wfu.type.trigger.api.dto.VerifyJwtTokenRequest;
import cc.wfu.types.exception.AppException;
import cc.wfu.types.model.Response;
import cc.wfu.types.snow.SnowflakeIdGenerator;
import cc.wfu.types.weixin.PaySignUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Objects;

/**
 * @Author: jia-qiang ljq1024.cc
 * @desc: 暴露给外界的sale接口
 * @Date: 2024-06-07-15:25
 */
@Slf4j
@RequestMapping("/sale/")
@RestController("sale_controller")
//@CrossOrigin(origins = {"${app.config.cross-origin}"})
public class SaleController implements SaleApi {

    @Resource
    private JwtAuthService jwtAuthService;
    @Resource
    private IProductOrder orderService;
    @Resource
    private EventPublisher eventPublisher;
    @Resource
    private OrderMessageEvent orderMessageEvent;
    @Resource
    private SnowflakeIdGenerator snowflakeIdGenerator;
    @Resource
    private IProductActivityArmory armory;

    /** 用户下单 createParOrder */
    @Override
    @RequestMapping(value = "create_pay_order/shopCarId", method = RequestMethod.POST)
    public Response<String> createParOrder(@RequestHeader("Authorization") String token, @RequestBody ShopCartEntity shopCartEntity) {
        try {
            log.info("用户下单 - 开始 - {}", JSON.toJSONString(shopCartEntity));
            // 1. token 校验 (Token 解析)
            String userStr = jwtAuthService.verifyJwtToken(VerifyJwtTokenRequest.builder().jwtToken(token).build());
            UserEntity userEntity = JSON.parseObject(userStr, UserEntity.class);
            if (!Objects.equals(userEntity.getUserId(), shopCartEntity.getUserId())) {
                log.warn("非法的操作：订单用户ID not equal 解析Token用户ID");
                throw new Exception();
            }
            log.info("用户商品下单，根据商品ID创建支付单开始 userId:{}, sku:{}", userEntity.getUserId(), shopCartEntity.getSku());
            // 2. 根据购物车对象创建订单对象
            SkuRechargeOrderEntity skuRechargeOrderEntity = SkuRechargeOrderEntity
                    .builder()
                    .sku(shopCartEntity.getSku())
                    .userId(shopCartEntity.getUserId())
                    .outBusinessNo(String.valueOf(snowflakeIdGenerator.nextId()))
                    .totalAmount(shopCartEntity.getTotalAmount())
                    .build();
            String payUrl = orderService.createSkuRechargeOrder(skuRechargeOrderEntity);
            log.info("用户商品下单，根据商品ID创建支付单完成 userId: {} sku: {} payUrl: {}", shopCartEntity.getUserId(), shopCartEntity.getSku(), payUrl);
            return Response.SUCCESS(payUrl);
        } catch (AppException e) {
            log.error("用户下单 - 出现业务异常", e);
            return Response.APP_ERROR(e.getMessage());
        } catch (Exception e) {
            log.error("用户下单 - 出现未知异常", e);
            return Response.UN_ERROR();
        }

    }

    @Value("${personal.wxpay.key}")
    private String personalKey;

    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 蓝图支付回调
     */
    @Override
    @PostMapping("ltzf/pay_notify")
    public void ltzyPayNotify(String code, String timestamp, String mch_id, String order_no, String out_trade_no, String pay_no, String total_fee, String sign, String pay_channel, String trade_type, String success_time, String attach, String openid, HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            log.info("code = {}", code);
            log.info("timestamp = {}", timestamp);
            log.info("mch_id = {}", mch_id);
            log.info("order_no = {}", order_no);
            log.info("out_trade_no = {}", out_trade_no);
            log.info("pay_no = {}", pay_no);
            log.info("total_fee = {}", total_fee);
            log.info("sign = {}", sign);
            log.info("pay_channel = {}", pay_channel);
            log.info("trade_type = {}", trade_type);
            log.info("success_time = {}", success_time);
            log.info("attach = {}", attach);
            log.info("openid = {}", openid);

            // 获取请求的地址
            String requestUrl = request.getRequestURL().toString();
            log.info("requestUrl = {}", requestUrl);

            // 判断签名
            boolean notifySign = PaySignUtil.checkNotifySign(timestamp, code, mch_id, order_no, out_trade_no,
                    pay_no,total_fee, sign, personalKey);
            if (!notifySign) {
                log.error("支付回调验证失败!");
                response.getWriter().write("FAIL");
                return;
            }

            // 支付成功
            if ("0".equals(code)) {
                log.info("支付成功 orderId:{} total:{} successTime: {}", out_trade_no, total_fee, success_time);
                // 支付成功 - 更新订单
                boolean isSuccess = orderService.changeOrderPaySuccess(out_trade_no, pay_no,
                        // 总金额转换为 BigDecimal 类型，然后除以 100，以还原为原始的金额值，
                        // 并使用 RoundingMode.HALF_UP 进行四舍五入保留两位小数
                        BigDecimal.valueOf(Double.parseDouble(total_fee)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP),
                        // 时间格式转换
                        dateFormat.parse(success_time));
                if (isSuccess) {
                    // 发布消息
                    eventPublisher.publish(orderMessageEvent.topic(), orderMessageEvent.buildEventMessage(out_trade_no));
                }
                response.getWriter().write("SUCCESS");
            } else {
                response.getWriter().write("FAIL");
            }

        } catch (Exception e) {
            log.error("支付失败", e);
            response.getWriter().write("FAIL");
        }
    }

    @PostMapping("/armory")
    @Override
    public void productActivityArmory(List<Long> skus) {
        log.info("装配开始。。。");
        if (skus.isEmpty()) return;
        for (Long sku : skus) {
            armory.assembleProductActivitySku(sku);
        }
    }


}
